﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace Axe.Windows.Forms
{
    public interface IBackManClient
    {
        object State { get; set; }
        bool IsEqual(object state1, object state2);
    }

    public class BackMan
    {
        public BackMan(IBackManClient client, int stackCapacity)
        {
            SetSize(stackCapacity);
            this.client = client;
            System.Windows.Forms.Application.Idle += new EventHandler(this.OnIdle);
        }

        public void Backward()
        {
            this.stackForward.Push(this.stateCurrent);
            this.stateCurrent = this.stackBackward.Pop();
            this.whileNavigate = true;
            this.client.State = this.stateCurrent;
        }

        public bool CanBackward()
        {
            return this.stackBackward.Count > 0;
        }

        public void Forward()
        {
            this.stackBackward.Push(this.stateCurrent);
            this.stateCurrent = this.stackForward.Pop();
            this.whileNavigate = true;
            this.client.State = this.stateCurrent;
        }

        public bool CanForward()
        {
            return this.stackForward.Count > 0;
        }

        public void Reset()
        {
            this.stackBackward.Clear();
            this.stackForward.Clear();
            this.stateCurrent = null;
        }

        public void SetSize(int stackCapacity)
        {
            this.stackBackward = new Stack(stackCapacity);
            this.stackForward = new Stack(stackCapacity);
        }

        protected void OnIdle(object sender, EventArgs e)
        {
            if (this.whileNavigate)
            {
                this.whileNavigate = false;
                return;
            }

            if (this.stateCurrent == null)
                this.stateCurrent = this.client.State;
            else
            {
                object stateNow = this.client.State;
                if (!this.client.IsEqual(stateNow,
                                          this.stateCurrent))
                {
                    this.stackBackward.Push(this.stateCurrent);
                    this.stateCurrent = stateNow;
                    this.stackForward.Clear();
                }
            }
        }

        protected IBackManClient client;
        protected bool whileNavigate;
        protected object stateCurrent;
        protected Stack stackBackward;
        protected Stack stackForward;
    }
}
